package com.sixfoot.foundation.mapping.service;

import java.io.Serializable;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.CrudRepository;
import org.springframework.transaction.annotation.Transactional;

import com.sixfoot.foundation.mapping.adapter.DtoAdapter;
import com.sixfoot.foundation.persistence.Identified;
import com.sixfoot.foundation.service.CrudService;

/**
 * 
 * @author six-foot
 *
 * @param <D> domain
 * @param <T> dto
 * @param <I> input data
 * @param <ID> identify
 */
@Transactional
public abstract class DtoCrudService<D extends Identified<ID>, T, I extends Identified<ID>, ID extends Serializable>
		implements CrudService<T, I, ID> {

	private CrudRepository<D, ID> repository;

	public CrudRepository<D, ID> getRepository() {
		return repository;
	}

	@Autowired
	public void setRepository(CrudRepository<D, ID> repository) {
		this.repository = repository;
	}

	@Autowired
	protected DtoAdapter<D, T, I> adapter;

	@Override
	public T add(I entity) {
		if (entity == null)
			return null;
		D d = this.adapter.convertToDo(entity);
		d = this.getRepository().save(d);
		T result = this.adapter.convertToDetailedDto(d);
		return result;
	}

	@Override
	public T update(I entity) {
		if (entity == null)
			return null;
		ID id = entity.getId();
		D d = getRepository().findOne(id);
		if (d == null)
			return null;
		d = this.adapter.update(entity, d);
		d = this.getRepository().save(d);
		T result = this.adapter.convertToDetailedDto(d);
		return result;
	}

	@Override
	public T findOne(ID id) {
		if (id == null)
			return null;
		D d = this.getRepository().findOne(id);
		if (d == null)
			return null;
		return this.adapter.convertToDetailedDto(d);
	}

	@Override
	public boolean exists(ID id) {
		return this.getRepository().exists(id);
	}

	@Override
	public List<T> findAll() {
		Iterable<D> all = this.getRepository().findAll();
		if (all == null)
			return null;
		return this.adapter.convertDoList(all);
	}

	@Override
	public List<T> findAll(Iterable<ID> ids) {
		Iterable<D> all = this.getRepository().findAll(ids);
		if (all == null)
			return null;
		return this.adapter.convertDoList(all);
	}

	@Override
	public long count() {
		return this.getRepository().count();
	}

	@Override
	public void delete(ID id) {
		if (id == null)
			return;
		this.getRepository().delete(id);
	}

	@Override
	public void delete(Iterable<ID> ids) {
		for (ID id : ids) {
			this.getRepository().delete(id);
		}
	}

	@Override
	public void deleteAll() {
		this.getRepository().deleteAll();
	}
}